#include "snake_app.h"

const int STEP_RATE_IN_MILLISECONDS = 125;


SnakeApp::SnakeApp(): window(nullptr), renderer(nullptr), joystick(nullptr) {
}

SnakeApp::~SnakeApp() {
    releaseJoyStick();
    closeWindow();
}

void SnakeApp::closeWindow() {
    if (renderer) {
        SDL_DestroyRenderer(renderer);
        renderer = nullptr;
    }
    if (window) {
        SDL_DestroyWindow(window);
        window = nullptr;
    }
}

SDL_AppResult SnakeApp::openWindow() {
    closeWindow();
    if (!SDL_CreateWindowAndRenderer("examples/demo/snake", 
        game.getWindowsWidth(), game.getWindowsHeight(), 0, &window, &renderer)) {
        return SDL_APP_FAILURE;
    }

    resourceManager.updateRenderer(renderer);
    last_step = SDL_GetTicks();

    return SDL_APP_CONTINUE;
}

SDL_AppResult SnakeApp::iterate() {
    const Uint64 now = SDL_GetTicks();

    // run game logic if we're at or past the time to run it.
    // if we're _really_ behind the time to run it, run it
    // several times.
    while ((now - last_step) >= STEP_RATE_IN_MILLISECONDS) {
        game.step();
        last_step += STEP_RATE_IN_MILLISECONDS;
    }

    game.draw(renderer, resourceManager);
    return SDL_APP_CONTINUE;
}

void SnakeApp::releaseJoyStick() {
    if (joystick) {
        SDL_CloseJoystick(joystick);
        joystick = nullptr;
    }
}
void SnakeApp::openJoyStick(SDL_JoystickID id) {
    if (!joystick) {
        joystick = SDL_OpenJoystick(id);
        if (!joystick) {
            SDL_Log("Failed to open joystick ID %u: %s", (unsigned int) id, SDL_GetError());
        }
    }
}

void SnakeApp::closeJoyStick(SDL_JoystickID id) {
    if (joystick && (SDL_GetJoystickID(joystick) == id)) {
        releaseJoyStick();
    }
}

SDL_AppResult SnakeApp::handle_hat_event(Uint8 hat) {
    switch (hat) {
        case SDL_HAT_RIGHT:
        game.redir(Direction::RIGHT);
            break;
        case SDL_HAT_UP:
        game.redir(Direction::UP);
            break;
        case SDL_HAT_LEFT:
        game.redir(Direction::LEFT);
            break;
        case SDL_HAT_DOWN:
        game.redir(Direction::DOWN);
            break;
        default:
            break;
        }
    return SDL_APP_CONTINUE;
}

SDL_AppResult SnakeApp::handle_key_event(SDL_Scancode key_code) {
    switch (key_code) {
    /* Quit. */
    case SDL_SCANCODE_ESCAPE:
    case SDL_SCANCODE_Q:
        return SDL_APP_SUCCESS;
    /* Restart the game as if the program was launched. */
    case SDL_SCANCODE_R:
    game.init();
        break;
    /* Decide new direction of the snake. */
    case SDL_SCANCODE_RIGHT:
        game.redir(Direction::RIGHT);
        break;
    case SDL_SCANCODE_UP:
    game.redir(Direction::UP);
        break;
    case SDL_SCANCODE_LEFT:
    game.redir(Direction::LEFT);
        break;
    case SDL_SCANCODE_DOWN:
    game.redir(Direction::DOWN);
        break;
    default:
        break;
    }
    return SDL_APP_CONTINUE;
}